package ias.deepsearch.com.helper.xposed.module;

import android.util.Log;
import android.util.SparseArray;

import com.google.gson.Gson;
import com.koushikdutta.async.http.Multimap;
import com.koushikdutta.async.http.server.AsyncHttpServer;
import com.koushikdutta.async.http.server.AsyncHttpServerRequest;
import com.koushikdutta.async.http.server.AsyncHttpServerResponse;
import com.koushikdutta.async.http.server.HttpServerRequestCallback;
import com.socks.library.KLog;
import com.yancloud.android.manager.IAPIBinder;
import com.yancloud.android.manager.PackageVersionPair;
import com.yancloud.android.manager.URLRegx;
import com.yancloud.android.reflection.get.Desc;
import com.yancloud.android.reflection.get.GetMessage;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import ias.deepsearch.com.helper.service.DaemonService;
import ias.deepsearch.com.helper.util.ShellUtils;

/**
 * Created by root on 6/27/17.
 */

public class VisiableManager {
    private static final String TAG="VisiableManager";
    static AsyncHttpServer server = null;
    static Object wm;
    public static void init(Object obj){
        if (server!=null || obj==null) return;
        Log.d(TAG,"init Server!");
        server = new AsyncHttpServer();
        server.get("/", new HttpServerRequestCallback() {
            @Override
            public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
                response.send("VisiableManager: Success!");

            }
        });
        DaemonService.register(VisiableManager.class,server);
        server.listen(6162);
        wm =obj;
    }


    @Desc("list help info")
    public static String help(String args){
        Method[] methods = VisiableManager.class.getDeclaredMethods();
        StringBuilder sb = new StringBuilder();
        for (Method m:methods){
            Desc desc = m.getAnnotation(Desc.class);
            if (desc==null)
                continue;
            sb.append(m.getName()+": ");
            sb.append(desc.value());
            sb.append("\n");
        }
        return sb.toString();
    }

    @Desc("list WindowState and pkgName")
    public static String listWindowState(String arg){
        StringBuilder sb = new StringBuilder();
        Map map  =VMHelper.getWindowMap(wm);
        for (Object windowState:map.values()){
            sb.append(VMHelper.getOwningPackage(windowState))
            .append("-->"+windowState.toString()).append("\n");
        }
        return sb.toString();
    }
    @Desc("hideApp")
    public static String hide(String pkg){
        Map map  =VMHelper.getWindowMap(wm);
        for (Object windowState:map.values()){
            String pkgName = VMHelper.getOwningPackage(windowState);
            if (pkgName.equals(pkg)){
                setVisiability(windowState,false);
                return "success";
            }
        }
        return "failed";
    }

    private static void setVisiability(Object windowState, boolean b) {
        Object token =  VMHelper.getWindowToken(windowState);
        if (token!=null) {
            Object ibinder = VMHelper.reverseGet(VMHelper.getTokenMap(wm), token);
            Log.d(TAG,"setVisiability: "+(ibinder==null)+" "+b);
            Object awtoken = VMHelper.getAppWindowToken(windowState);
            VMHelper.WMS.setAppVisiability(wm,ibinder,b);
        }
    }
    @Desc("relayout")
    public static String relayout(String arg){
        return VMHelper.WMS.performLayoutAndPlaceSurfacesLocked(wm);
    }

    @Desc("showApp")
    public static String show(String pkg){
        Map map  =VMHelper.getWindowMap(wm);
        for (Object windowState:map.values()){
            String pkgName = VMHelper.getOwningPackage(windowState);
            if (pkgName.equals(pkg)){
                Object fws = VMHelper.WMS.getFocursedWS(wm);
                setVisiability(windowState,true);
                setVisiability(fws,false);
                relayout(null);
                return "success";
            }
        }
        return "failed";
    }

    @Desc("show taskids")
    public static String listTaskID(String args){
        SparseArray array = VMHelper.WMS.getTaskIDtoTask(wm);
        StringBuilder sb = new StringBuilder();
        for (int i=0;i<array.size();i++){
            if (array.valueAt(i)!=null)
                sb.append(i).append("-->").append(array.valueAt(i).toString());
        }
        return sb.toString();
    }

    @Desc("moveToTop")
    public static String moveToTop(String id){
       return VMHelper.moveTaskToTop(wm,Integer.valueOf(id));
    }

    @Desc("moveToBottom")
    public static String moveToBottom(String id){
        return VMHelper.WMS.moveTaskToBottom(wm,Integer.valueOf(id));
    }

    @Desc(" showCircularMask")
    public static String  showCircularMask(String arg){
        return VMHelper.WMS.showCircularMask(wm,Boolean.valueOf(arg));
    }



    public static Method canHandle(String method) {
        try {
            Method m = VisiableManager.class.getDeclaredMethod(method, String.class);
            if (m!=null && m.getAnnotation(Desc.class)!=null)
            return m;
            else return null;
        }catch(Exception e){
            return null;
        }
    }

    public static String handle(String pkgName,String method, String arg){
        try {
            Method m = canHandle(method);
            if (m != null)
                return (String) m.invoke(null, arg);
            else return "unsupported method:"+method;
        }catch(Exception e){
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            e.printStackTrace(new PrintStream(bo));
            return bo.toString();
        }
    }

    @URLRegx("/VisiableManager")
    public static void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
        Multimap query = request.getQuery();
        String getMessage = query.getString("getMessage");
        GetMessage message = new Gson().fromJson(getMessage, GetMessage.class);
        response.send(VisiableManager.handle(message.pkgName,message.method,message.arg));
    }
}


